package com.juyu.miliao.api.service;

import com.alibaba.fastjson.JSONObject;
import com.juyu.miliao.api.constant.DepositType;
import com.juyu.miliao.api.dao.mysql.*;
import com.juyu.miliao.api.dao.redis.DiamondRedisDao;
import com.juyu.miliao.api.dao.redis.LineTimeRedisDao;
import com.juyu.miliao.api.domain.*;
import com.juyu.miliao.api.domain.vo.GiftSpendVo;
import com.juyu.miliao.api.exception.WrongNoDepositException;
import com.juyu.miliao.api.handler.IntegralRewardsAndPunishmentsHandler;
import com.juyu.miliao.api.handler.UserInvitationIncomeDetailsHandler;
import com.juyu.miliao.api.rabbitMQ.GiftWallRabbitMq;
import com.juyu.miliao.api.util.PageUtil;
import com.juyu.miliao.api.util.SegmentedLock;
import com.juyu.miliao.common.constant.BeansType;
import com.juyu.miliao.common.constant.enumRedisKey.EnumRedisKey;
import com.juyu.miliao.common.domain.BillDetailBeans;
import com.juyu.miliao.common.exception.ConsumeRuntimeException;
import com.juyu.miliao.common.util.ArrayUtil;
import com.juyu.miliao.common.util.DoubleFormatUtil;
import com.juyu.miliao.common.util.GiftSpendGiveBeans;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class GiftSpendService {
    private final SegmentedLock segmentedLock = new SegmentedLock(17);
    @Resource
    private GiftSpendDao giftSpendDao;
    @Resource
    private GiftService giftService;
    @Resource
    private UserWalletDao userWalletDao;
    @Resource

    private BillDetailDao billDetailDao;
    @Resource
    private UserCountDao userCountDao;
    @Resource
    private RedisTemplateService redisTemplateService;
    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private GiftWallRabbitMq giftWallRabbitMq;
    @Resource
    private VestRobotMessageService vestRobotMessageService;
    @Resource
    private IntegralLevelInfoService integralLevelInfoService;
    @Resource
    private DiamondRedisDao diamondRedisDao;
    @Resource
    private UserInvitationIncomeDetailsHandler userInvitationIncomeDetailsHandler;
    @Resource
    private IntegralRewardsAndPunishmentsHandler integralRewardsAndPunishmentsHandler;
    @Resource
    private LineTimeRedisDao lineTimeRedisDao;
    @Resource
    private ActiveGiftDao activeGiftDao;

    private final Logger logger = LoggerFactory.getLogger(GiftSpendService.class);
    /**
     * 获取用户收到礼物列表
     *
     * @param inUserId
     * @param pageSize
     * @param page
     * @return
     */
    public List<GiftSpend> findGiftSpendByInUserId(int inUserId, int page, int pageSize) {
        int startNum = PageUtil.getOffset(page, pageSize);
        return giftSpendDao.findGiftSpendByInUserId(inUserId, startNum, pageSize);
    }

    /**
     * 礼物来往记录
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveGiftSpend(GiftSpend entity) {
        User user = userInfoDao.getUserById(entity.getOutUserId());
        // 获取礼物信息
        Gift gift = giftService.getGiftById(entity.getGiftId());
        if (user.getIsVip() == 2 && user.getIsSvip()==2 && user.getIsPlatinumVip()==2 && gift.getType() == 2) {
            throw new ConsumeRuntimeException("您不是vip");
        }
        // 获取帐号钱包
        UserWallet userWallet = userWalletDao.getUserWalletById(entity.getOutUserId());
        // 判断钱包金币是否够用
        int price = gift.getPrice();
        if(user.getIsVip()==1 || user.getIsSvip()==1 || user.getIsPlatinumVip()==1){
            price = gift.getVipPrice();
        }
        if ((price * entity.getNum()) > userWallet.getDeposit()) {
            throw new WrongNoDepositException("金币不足");
        } else {
            // 获取礼物转换钻石比例
//            Appkey appkey = appkeyService.getAppKeyByKey("giftRatio");
            BigDecimal diamondConversionRate = integralLevelInfoService
                    .getDiamondConversionRate(entity.getInUserId());
            entity.setSpend(price * entity.getNum());
            // 金币转换钻石
            double diamond = DoubleFormatUtil.doubleFormate(price * diamondConversionRate.doubleValue()* entity.getNum());
            entity.setDiamond(diamond);
            // 消费者,修改剩余金币
            userWallet.setDeposit((price * entity.getNum()));
            int num = userWalletDao.minusDeposit(userWallet);
            if (num != 1) {
                throw new WrongNoDepositException("金币不足");
            }
            // 保存礼物来往记录
            giftSpendDao.insertGiftSpend(entity);
            // 保存消费记录
//            BillDetail billDetail = new BillDetail();
//            billDetail.setRecordType(4);// 消费类型4 送礼物
//            billDetail.setInUserId(entity.getInUserId());// 赚取钻石用户id
//            billDetail.setOutUserId(entity.getOutUserId());// 消费金币用户id
//            billDetail.setDiamond(diamond);// 赚取钻石数
//            billDetail.setSpend(entity.getSpend());// 消费金币数
//            billDetailDao.insertBillDetail(billDetail);

            BillDetailDeposit billDetailDeposit = new BillDetailDeposit();
            billDetailDeposit.setRecordType(2); //消费类型2 送礼物
            billDetailDeposit.setInUserId(entity.getInUserId());// 赚取钻石用户id
            billDetailDeposit.setOutUserId(entity.getOutUserId());// 消费金币用户id
            billDetailDeposit.setSpend(-entity.getSpend());// 消费金币数
            billDetailDeposit.setDiamond(diamond);// 赚取钻石数
            billDetailDeposit.setRatio(diamondConversionRate.doubleValue());//转换比例
            User inUser =  userInfoDao.selectAdminByUnionId(entity.getInUserId());
            if(inUser!=null){
                billDetailDeposit.setUnionId(inUser.getUnionId());
                billDetailDeposit.setAgentId(inUser.getAgentId());
                billDetailDeposit.setAdminId(inUser.getAdminId());
            }
            billDetailDao.insertBillDetailDeposit(billDetailDeposit);

            integralRewardsAndPunishmentsHandler.diamondsForIntegralBy100(entity.getInUserId(),
                    diamond);

            // 收款者，修改剩余钻石
            UserWallet inUserWallet = userWalletDao.getUserWalletById(entity.getInUserId());
            inUserWallet.setDiamond(diamond);
            userWalletDao.reviseDiamond(inUserWallet);
            userCountDao.updateGiftDiamond(billDetailDeposit.getInUserId(),billDetailDeposit.getDiamond());
            diamondRedisDao.setHomeListIncomeByHostUser(entity.getInUserId(),billDetailDeposit.getDiamond());
            //钻石榜统计
            diamondRedisDao.setRankingDiamondList(LocalDate.now(),diamond,String.valueOf(entity.getInUserId()));

            userInvitationIncomeDetailsHandler.incomeDiamondsDetails(entity.getInUserId(),
                    DepositType.PAY_SEND_GIFT.getCode(),new BigDecimal(diamond+""));
            // 用户统计m值
//            userCountDao.addMGradeSum(billDetail.getInUserId(), billDetail.getDiamond());
            // 用户统计v值(6.19-土豪值只从充值和获取金币处计算)
            // userCountDao.addVGradeSum(billDetail.getOutUserId(),
            // billDetail.getSpend());
            // 排行榜统计(6.19-土豪值只从充值和获取金币处计算)
//            redisTemplateService.setMUserSort(billDetail.getInUserId(), billDetail.getDiamond());
            // redisTemplateService.setVUserSort(billDetail.getOutUserId(),
            // billDetail.getSpend());
            GiftSpend giftSpend = giftSpendDao.getGiftSendInfoBySendId(entity.getSpendId());
            if (giftSpend != null) {
                giftWallRabbitMq.setGiftWallMessage(JSONObject.toJSONString(giftSpend));
                giftWallRabbitMq.sendGiftWallMessage(giftSpend);
            }
            if ((price * entity.getNum()) > 8000) {
                logger.info("礼物大于50发送消息");
                sendPrivateMessage(entity,gift,user);
            }
            //赠送礼物会返寻豆
            //giftSpendGiveBeans(entity);
            //礼物争夺战
            activeGiftSave(entity);

        }
    }

    /**
     * 礼物争夺战
     */
    private void activeGiftSave(GiftSpend entity){
        String activeDate = LocalDate.now().toString(); // 获取当前年月日
        ActiveGift activeGift = activeGiftDao.getActiveGiftSwitchInfo(activeDate);
        Optional<ActiveGift> optActiveGift = Optional.ofNullable(activeGift);
        long nowEpoch = Instant.now().getEpochSecond(); // 获取当前时间戳(秒)
        long activeStarEpoch = LocalDateTime.now().withHour(20).withMinute(0).withSecond(0)
                .toInstant(ZoneOffset.of("+8")).getEpochSecond();
        if(optActiveGift.isPresent() && activeGift.getGiftId()==entity.getGiftId()
                && (nowEpoch >= activeStarEpoch)){
            //维护active_gift_config
            activeGiftDao.updateActiveGiftGainNum(activeGift.getId(),entity.getNum());
            //维护active_gift_ranking
            User user = userInfoDao.getUserInfoById(entity.getInUserId());
            activeGiftDao.insertActiveGiftRanking(activeDate,user.getUserId(),user.getIcon()
                    ,user.getNickName(),entity.getNum());
        }
    }


    /**
     * 赠送礼物会返寻豆
     * @param entity
     */
    private void giftSpendGiveBeans(GiftSpend entity) {
        //获取随机返还倍数
        int ratio = GiftSpendGiveBeans.getGiveBeansRatio();
        int beans = entity.getSpend() * ratio;
        BillDetailBeans billDetailBeans = new BillDetailBeans();
        billDetailBeans.setBeansType(BeansType.SPEND_GIFT_GIVE_BEANS.getCode());
        billDetailBeans.setBeans(Long.parseLong(beans+""));
        billDetailBeans.setRatio(ratio);
        billDetailBeans.setUserId(Long.parseLong(entity.getOutUserId()+""));
        billDetailDao.insertBillDetailBeans(billDetailBeans);
        userWalletDao.addBeans(entity.getOutUserId(),beans);
    }

    private void sendPrivateMessage(GiftSpend entity,Gift gift,User outUser){
        Set<Object> userSet = lineTimeRedisDao.getLineHashKeys();
        if (userSet.size()==0 && userSet.size()==0){
            logger.info("发送消息礼物：没有在线用户");
            return;
        }
        User inUser = userInfoDao.getUserInfoById(entity.getInUserId());
        if(userSet.size()>0){
            logger.info("发送消息礼物：userSet——————"+userSet);
            Long[] userIdArray = userSet.stream().map(i->Long.parseLong(i.toString()))
                    .collect(Collectors.toSet()).toArray(new Long[userSet.size()]);
            JSONObject body = new JSONObject();
            body.put("clickUserId", entity.getInUserId());
            body.put("message", outUser.getNickName()+"送给"+inUser.getNickName()
                    +gift.getGiftName()+"*"+entity.getNum());
            body.put("giftName", gift.getGiftName());
            body.put("giftIcon", gift.getIcon());
            body.put("giftNum", entity.getNum());
            body.put("inUser",inUser.getNickName());
            body.put("outUser",outUser.getNickName());
            splitArraySendMessage(userIdArray,body);
        }
    }

    private void splitArraySendMessage(Long[] userIdArray,JSONObject body){
        if (userIdArray.length >= 450) {
            List<Long[]> subAry = ArrayUtil.splitAry(userIdArray, 450);//分割后的子块数组
            for (Long[] obj : subAry) {//打印输出结果
                vestRobotMessageService.getSendGiftSpendMessage(body.toString(),obj);
            }
        }else{
            vestRobotMessageService.getSendGiftSpendMessage(body.toString(),userIdArray);
        }
    }
    /**
     * 聊天时赠送金币红包
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveGiveSpend(BillDetail entity) {
        // 获取用户钱包
        UserWallet userWallet = userWalletDao.getUserWalletById(entity.getOutUserId());
        // 判断钱包金币是否够用
        if (entity.getSpend() > userWallet.getDeposit()) {
            throw new WrongNoDepositException("金币不足");
        } else {
            // 获取金币兑换钻石比例
//            Appkey appkey = appkeyService.getAppKeyByKey("giftRatio");
            BigDecimal diamondConversionRate = integralLevelInfoService
                    .getDiamondConversionRate(entity.getInUserId());
            // 金币转换钻石
            double diamond = DoubleFormatUtil.doubleFormate(entity.getSpend() * diamondConversionRate.doubleValue());
            // 保存消费记录
            BillDetail billDetail = new BillDetail();
            billDetail.setRecordType(5);// 消费类型 5送红包
            billDetail.setInUserId(entity.getInUserId());// 赚取钻石用户id
            billDetail.setOutUserId(entity.getOutUserId());// 消费金币用户id
            billDetail.setDiamond(diamond);// 赚取钻石数
            billDetail.setSpend(entity.getSpend());// 消费金币数
            billDetailDao.insertBillDetail(billDetail);
            // 消费者,修改剩余金币
            userWallet.setDeposit(entity.getSpend());
            userWalletDao.minusDeposit(userWallet);
            // 收款者，修改剩余钻石
            UserWallet inUserWallet = userWalletDao.getUserWalletById(entity.getInUserId());
            inUserWallet.setDiamond(diamond);
            userWalletDao.reviseDiamond(inUserWallet);
            // 用户统计m值
            userCountDao.addMGradeSum(billDetail.getInUserId(), billDetail.getDiamond());

            userCountDao.updateGiftDiamond(billDetail.getInUserId(),billDetail.getDiamond());
            // 用户统计v值(6.19-土豪值只从充值和获取金币处计算)
            // userCountDao.addVGradeSum(billDetail.getOutUserId(),
            // billDetail.getSpend());
            // 排行榜统计(6.19-土豪值只从充值和获取金币处计算)
            redisTemplateService.setMUserSort(billDetail.getInUserId(), billDetail.getDiamond());
            // redisTemplateService.setVUserSort(billDetail.getOutUserId(),
            // billDetail.getSpend());
        }
    }

    //获取主播收到的全部礼物(全部展示，不分页)
    public List<GiftSpend> gitGiftSpendByInUserId(long id) {
        return giftSpendDao.gitGiftSpendByInUserId(id);
    }

    public List<GiftSpendVo> getUserGiftList(long id, int giftId, Integer page, Integer pageSize) {
        List<GiftSpendVo> list = new ArrayList<>();
        int startNum = PageUtil.getOffset(page, pageSize);
        List<GiftSpend> spendList = giftSpendDao.getUserGiftList(id,giftId,startNum,pageSize);
        if(spendList.size()==0)
            return new ArrayList<>();
        for (GiftSpend giftSpend: spendList  ) {
            User user = userInfoDao.getUserById(giftSpend.getOutUserId());
            GiftSpendVo giftSpendVo = new GiftSpendVo();
            giftSpendVo.setUserName(user.getNickName());
            giftSpendVo.setNums(giftSpend.getNum());
            list.add(giftSpendVo);
        }
        return list;
    }

}

